<!DOCTYPE html>
<html>
<!-- 
    author: skwang （skvdhsh@gmail.com）
    desc: SlioChat - 一个现代化的、功能丰富的单文件大模型AI聊天应用
-->
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
    <title>SlioChat - Beta测试</title>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232563eb' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M12 2C6.5 2 2 6.5 2 12s4.5 10 10 11c.9 0 1.8-.1 2.6-.4'/><path d='M17.6 14.2c-.8.8-1.3 2-1.1 3.2.2 1.2 1.1 2.2 2.3 2.4 1.2.2 2.4-.3 3.2-1.1.8-.8 1.3-2 1.1-3.2-.2-1.2-1.1-2.2-2.3-2.4-1.2-.2-2.4.3-3.2 1.1z'/><path d='M9.4 9.8c.8-.8 1.3-2 1.1-3.2-.2-1.2-1.1-2.2-2.3-2.4-1.2-.2-2.4.3-3.2 1.1-.8.8-1.3 2-1.1 3.2.2 1.2 1.1 2.2 2.3 2.4 1.2.2 2.4-.3 3.2-1.1z'/><path d='M14.5 8.5l-5 7'/></svg>">
    <!-- 可以换成本地文件或者其他cdn服务 -->
    <script src="https://cdn.tailwindcss.com/3.4.16"></script>
    <script src="https://s4.zstatic.net/npm/marked/marked.min.js"></script>
    <link rel="stylesheet" href="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/highlight.js/11.4.0/styles/github-dark.min.css">
    <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/highlight.js/11.4.0/highlight.min.js"></script>
    <script src="https://lf26-cdn-tos.bytecdntp.com/cdn/expire-1-M/jschardet/3.0.0/jschardet.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/mammoth/1.6.0/mammoth.browser.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js"></script>

    <style>
        /* 主题变量 */
        :root {
            --bg-primary: #ffffff;
            --bg-secondary: #f3f4f6;
            --text-primary: #111827;
            --text-secondary: #4b5563;
            --border-color: #e5e7eb;
            --hover-bg: #f9fafb;
            --message-bg-user: #ebf5ff;
            --message-bg-assistant: #f3f4f6;
            --button-primary-bg: #2563eb;
            --button-primary-hover: #1d4ed8;
            --button-primary-text: #ffffff;
        }

        :root[data-theme="dark"] {
            --bg-primary: #111827;
            --bg-secondary: #1f2937;
            --text-primary: #f9fafb;
            --text-secondary: #d1d5db;
            --border-color: #374151;
            --hover-bg: #374151;
            --message-bg-user: #1e3a8a;
            --message-bg-assistant: #1f2937;
            --button-primary-bg: #3b82f6;
            --button-primary-hover: #2563eb;
            --button-primary-text: #ffffff;
        }

        /* 全局过渡效果 */
        *, *::before, *::after {
            transition-property: background-color, border-color, color, fill, stroke;
            transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
            transition-duration: 0.15s;
        }

        .no-transition {
            transition: none !important;
        }

        body {
            background-color: var(--bg-primary);
            color: var(--text-primary);
            transition: background-color 0.3s ease, color 0.3s ease;
        }

        /* Markdown 样式 */
        .markdown-body pre {
            background-color: var(--bg-secondary);
            border-radius: 0.5rem;
            padding: 1rem;
            margin: 1rem 0;
            overflow-x: auto;
            border: 1px solid var(--border-color);
            max-width: 100%;
            white-space: pre-wrap;
            word-wrap: break-word;
            position: relative;
            /* 日间模式下的代码块背景 */
            background-color: #ffffff;
        }

        .markdown-body pre code {
            font-family: monaco, Consolas, "Lucida Console", monospace;
            font-size: 0.9em;
            background-color: transparent;
            padding: 0;
            border-radius: 0;
            /* 日间模式下的代码文本颜色 */
            color: #24292e;
        }

        .markdown-body p {
            margin: 0.5rem 0;
            line-height: 1.6;
            max-width: 100%;
        }

        .markdown-body ul, .markdown-body ol {
            margin: 0.5rem 0;
            padding-left: 1.5rem;
        }

        .markdown-body li {
            margin: 0.25rem 0;
        }

        .markdown-body blockquote {
            border-left: 4px solid #4a5568;
            padding-left: 1rem;
            margin: 1rem 0;
            color: #718096;
        }

        .dark .markdown-body blockquote {
            border-left-color: #718096;
            color: #a0aec0;
        }

        /* 思考容器样式 */
        .think-container {
            margin: 1rem 0;
            border: 1px solid var(--border-color);
            border-radius: 0.5rem;
            overflow: hidden;
        }

        .think-header {
            display: flex;
            align-items: center;
            gap: 0.5rem;
            padding: 0.75rem 1rem;
            background-color: var(--bg-secondary);
            border-bottom: 1px solid var(--border-color);
            cursor: pointer;
            user-select: none;
            transition: background-color 0.2s ease;
        }
        
        .think-header:hover {
            background-color: var(--hover-bg);
        }
        
        .think-header-icon {
            transform: rotate(0deg);
            transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
        }
        
        .think-content.collapsed + .think-header .think-header-icon {
            transform: rotate(-90deg);
        }

        .think-content {
            padding: 1rem;
            background-color: var(--bg-primary);
            transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            overflow: hidden;
        }

        .think-content.collapsed {
            padding-top: 0;
            padding-bottom: 0;
            margin-top: 0;
            margin-bottom: 0;
            border-top: 0;
            border-bottom: 0;
            opacity: 0;
            transform: translateY(-10px);
        }

        /* 光标动画 */
        .cursor {
            display: inline-block;
            width: 2px;
            height: 1em;
            background: currentColor;
            margin-left: 2px;
            animation: blink 1s infinite;
        }

        @keyframes blink {
            0%, 100% { opacity: 1; }
            50% { opacity: 0; }
        }

        /* 消息操作按钮 */
        .message-actions {
            opacity: 0;
            transition: opacity 0.2s;
        }

        .message-container:hover .message-actions {
            opacity: 1;
        }

        @media (max-width: 768px) {
            .message-actions {
                opacity: 1;
            }
            .markdown-body pre {
                max-width: 100%;
                font-size: 0.85em;
            }
        }

        /* 对话列表项样式 */
        .conversation-item {
            transition: all 0.2s ease-in-out;
            position: relative;
        }

        .conversation-item:hover {
            background-color: var(--bg-secondary);
        }

        .conversation-item.active {
            background-color: var(--message-bg-user);
            border-left: 4px solid var(--button-primary-bg);
        }

        /* 侧边栏响应式 */
        .sidebar {
            transition: transform 0.3s ease-in-out;
        }

        @media (max-width: 768px) {
            .sidebar {
                position: fixed;
                top: 0;
                left: 0;
                bottom: 0;
                z-index: 50;
                transform: translateX(-100%);
            }
            .sidebar.active {
                transform: translateX(0);
            }
            #sidebar-overlay.active {
                display: block;
            }
        }

        /* 主题切换按钮 */
        #theme-toggle {
            position: relative;
            overflow: hidden;
        }

        #theme-toggle::after {
            content: '';
            position: absolute;
            inset: 0;
            background-color: currentColor;
            opacity: 0;
            transition: opacity 0.2s;
        }

        #theme-toggle:hover::after {
            opacity: 0.1;
        }

        /* 主题切换动画 */
        .theme-transition {
            animation: theme-fade 0.3s ease;
        }

        @keyframes theme-fade {
            from { opacity: 0.8; }
            to { opacity: 1; }
        }

        /* Toast提示 */
        .theme-toast {
            position: fixed;
            bottom: 1rem;
            right: 1rem;
            background-color: var(--bg-secondary);
            color: var(--text-primary);
            padding: 0.5rem 1rem;
            border-radius: 0.5rem;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
            animation: toast-fade 0.3s ease-in-out;
        }

        @keyframes toast-fade {
            from {
                opacity: 0;
                transform: translateY(1rem);
            }
            to {
                opacity: 1;
                transform: translateY(0);
            }
        }

        /* 确保所有颜色相关的样式使用 CSS 变量 */
        .markdown-body {
            color: var(--text-primary);
        }

        /* 回到最新按钮样式 */
        #scroll-to-bottom-btn {
            position: fixed;
            bottom: 80px;
            right: 20px;
            padding: 8px 16px;
            background-color: var(--button-primary-bg);
            color: var(--button-primary-text);
            border-radius: 20px;
            cursor: pointer;
            opacity: 0;
            transform: translateY(20px);
            transition: opacity 0.3s, transform 0.3s;
            z-index: 40;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
        }
        
        #scroll-to-bottom-btn.visible {
            opacity: 1;
            transform: translateY(0);
        }
        
        #scroll-to-bottom-btn:hover {
            background-color: var(--button-primary-hover);
        }

        /* 移动设备安全区域适配 */
        @supports(padding-bottom: env(safe-area-inset-bottom)) {
            .pb-safe {
                padding-bottom: env(safe-area-inset-bottom, 0);
            }
        }
        
        /* 移动设备输入区域适配 */
        @media (max-width: 768px) {
            #chat-container {
                padding-bottom: 0.25rem;
            }
            
            .pb-safe {
                padding-bottom: max(0.5rem, env(safe-area-inset-bottom, 0.5rem));
            }
        }

        /* PC端输入区域适配 */
        @media (min-width: 769px) {
            .pb-safe {
                padding-bottom: 0;
            }
        }

        /* 模型选择按钮样式 */
        .model-btn {
            border-color: var(--border-color);
            color: var(--text-secondary);
            background-color: var(--bg-primary);
        }
        
        .model-btn:hover {
            background-color: var(--hover-bg);
        }
        
        .model-btn.active {
            background-color: var(--button-primary-bg);
            border-color: var(--button-primary-bg);
            color: var(--button-primary-text);
        }
        
        @media (max-width: 768px) {
            .model-btn {
                padding: 0.375rem 0.75rem;
            }
        }

        /* 分割线样式 */
        .markdown-body hr {
            height: 2px;
            background-color: var(--border-color);
            border: none;
            margin: 2rem 0;
        }

        /* 复制成功提示样式 */
        .copy-toast {
            position: fixed;
            bottom: 16px;
            right: 16px;
            background-color: var(--bg-primary);
            color: var(--text-primary);
            padding: 8px 16px;
            border-radius: 8px;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
            display: flex;
            align-items: center;
            gap: 8px;
            z-index: 100;
            animation: toast-slide-up 0.3s ease, toast-fade-out 0.3s ease 1.7s forwards;
        }
        
        @keyframes toast-slide-up {
            from {
                transform: translateY(100%);
                opacity: 0;
            }
            to {
                transform: translateY(0);
                opacity: 1;
            }
        }
        
        @keyframes toast-fade-out {
            from {
                opacity: 1;
            }
            to {
                opacity: 0;
            }
        }

        /* 确保所有内容都不会超出容器 */
        .markdown-body {
            overflow-wrap: break-word;
            word-wrap: break-word;
            word-break: break-word;
            hyphens: auto;
        }
        
        /* 处理长链接 */
        .markdown-body a {
            word-break: break-all;
        }
        
        /* 处理表格 */
        .markdown-body table {
            display: block;
            width: 100%;
            overflow-x: auto;
            max-width: 100%;
            border-spacing: 0;
            border-collapse: collapse;
        }
        
        .markdown-body table th,
        .markdown-body table td {
            padding: 0.75rem 1.5rem;
            border: 1px solid var(--border-color);
        }
        
        .markdown-body table tr {
            background-color: var(--bg-primary);
            border-top: 1px solid var(--border-color);
        }
        
        .markdown-body table tr:nth-child(2n) {
            background-color: var(--bg-secondary);
        }
        
        .markdown-body table th {
            font-weight: 600;
            background-color: var(--bg-secondary);
        }
        
        /* 处理图片 */
        .markdown-body img {
            max-width: 100%;
            height: auto;
        }
        
        /* 处理行内代码 */
        .markdown-body code {
            word-break: break-all;
            white-space: pre-wrap;
        }

        /* 代码块复制按钮 */
        .code-copy-btn {
            position: absolute;
            top: 0.5rem;
            right: 0.5rem;
            padding: 0.25rem 0.5rem;
            color: var(--text-secondary);
            background-color: var(--bg-primary);
            border: 1px solid var(--border-color);
            border-radius: 0.25rem;
            opacity: 1;
            cursor: pointer;
            z-index: 10;
            display: flex;
            align-items: center;
            gap: 0.25rem;
            font-size: 0.75rem;
            transition: all 0.2s ease;
        }

        .code-copy-btn:hover {
            opacity: 1;
            background-color: var(--hover-bg);
        }

        /* 移动端样式优化 */
        @media (max-width: 768px) {
            .code-copy-btn {
                opacity: 1;
                padding: 0.25rem 0.5rem;
            }
        }

        .code-copy-btn.copied {
            color: var(--button-primary-bg);
        }

        /* 深色模式覆盖 */
        :root[data-theme="dark"] .markdown-body pre {
            background-color: var(--bg-secondary);
        }

        :root[data-theme="dark"] .markdown-body pre code,
        :root[data-theme="dark"] .markdown-body code {
            color: var(--text-primary);
        }

        :root[data-theme="dark"] .markdown-body code {
            background-color: var(--bg-secondary);
        }

        /* Markdown 样式 */
        .markdown-body h1,
        .markdown-body h2,
        .markdown-body h3 {
            margin-top: 1.25rem;
            margin-bottom: 0.75rem;
            font-weight: 600;
        }

        /* 标题样式 */
        .markdown-body h1 {
            font-size: 1.5em;
        }
        
        .markdown-body h2 {
            font-size: 1.3em;
        }
        
        .markdown-body h3 {
            font-size: 1.15em;
        }
        
        .markdown-body h4 {
            font-size: 1.05em;
            margin-top: 1rem;
            margin-bottom: 0.5rem;
            font-weight: 600;
        }
        
        .markdown-body h5 {
            font-size: 1em;
            margin-top: 1rem;
            margin-bottom: 0.5rem;
            font-weight: 600;
        }
        
        .markdown-body h6 {
            font-size: 0.95em;
            margin-top: 1rem;
            margin-bottom: 0.5rem;
            font-weight: 600;
        }

        /* 自定义滚动条样式 */
        #conversation-list::-webkit-scrollbar {
            width: 6px;
        }
        
        #conversation-list::-webkit-scrollbar-track {
            background: transparent;
        }
        
        #conversation-list::-webkit-scrollbar-thumb {
            background-color: var(--border-color);
            border-radius: 3px;
        }
        
        #conversation-list::-webkit-scrollbar-thumb:hover {
            background-color: var(--text-secondary);
        }
        
        /* Firefox 滚动条样式 */
        #conversation-list {
            scrollbar-width: thin;
            scrollbar-color: var(--border-color) transparent;
        }

        /* 输入区域样式 */
        .input-area {
            border-top: 1px solid var(--border-color);
            padding: 1rem;
        }

        @media (max-width: 768px) {
            .input-area {
                padding: 0.5rem; /* 减小手机端的内边距 */
            }
            
            .input-area textarea {
                height: 5rem; /* 减小手机端的输入框高度 */
            }
        }

        /* 修改链接样式 */
        .markdown-body a {
            color: #3b82f6; /* 使用更鲜明的蓝色 */
            text-decoration: none;
            position: relative;
            transition: all 0.2s ease;
            font-weight: 500; /* 稍微加粗 */
            padding: 0 2px; /* 添加一点内边距 */
        }

        .markdown-body a:hover {
            color: #2563eb; /* 悬停时的颜色 */
            background-color: rgba(59, 130, 246, 0.1); /* 添加淡蓝色背景 */
            border-radius: 2px;
        }

        /* 深色模式下的链接颜色调整 */
        :root[data-theme="dark"] .markdown-body a {
            color: #60a5fa; /* 深色模式下使用更亮的蓝色 */
            opacity: 1;
        }

        :root[data-theme="dark"] .markdown-body a:hover {
            color: #93c5fd;
            background-color: rgba(96, 165, 250, 0.2);
        }

        /* 为外部链接添加图标 */
        .markdown-body a[href^="http"]::before {
            content: '';
            display: inline-block;
            width: 12px;
            height: 12px;
            margin-right: 4px;
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%233b82f6'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14'/%3E%3C/svg%3E");
            background-size: contain;
            background-repeat: no-repeat;
            vertical-align: middle;
        }

        :root[data-theme="dark"] .markdown-body a[href^="http"]::before {
            background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke='%2360a5fa'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14'/%3E%3C/svg%3E");
        }

        /* 加载动画样式 */
        @keyframes dot-bounce {
            0%, 80%, 100% { transform: translateY(0); }
            40% { transform: translateY(-4px); }
        }

        .loading-dots {
            display: flex;
            align-items: center;
            gap: 4px;
            padding: 8px 0;
        }

        .loading-dots .dot {
            width: 6px;
            height: 6px;
            background-color: var(--text-secondary);
            border-radius: 50%;
            animation: dot-bounce 1.4s infinite ease-in-out both;
        }

        .loading-dots .dot:nth-child(1) { animation-delay: -0.32s; }
        .loading-dots .dot:nth-child(2) { animation-delay: -0.16s; }
        .loading-dots .dot:nth-child(3) { animation-delay: 0s; }

        /* 修复输入框右边框问题 */
        #user-input {
            outline: none !important;
            box-shadow: none !important;
        }
        
        #user-input:focus {
            border-color: var(--button-primary-bg);
            box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
            outline: none;
        }
        
        /* 确保输入框在所有状态下都有一致的边框 */
        #user-input:focus-visible {
            outline: none;
        }
        
        /* 移除任何可能的浏览器默认样式 */
        textarea {
            appearance: none;
            -webkit-appearance: none;
        }
        
        /* 确保在所有浏览器中一致的行为 */
        textarea:focus {
            outline: none;
        }
        
        /* 修复可能的 Chrome 特定问题 */
        @supports (-webkit-appearance: none) {
            #user-input:focus {
                outline: none !important;
            }
        }
        
        /* 修复可能的 Firefox 特定问题 */
        @-moz-document url-prefix() {
            #user-input:focus {
                box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.2);
                border-color: var(--button-primary-bg);
            }
        }

        /* 文件预览关闭按钮样式 */
        .file-preview {
            position: relative;
        }
        
        .file-close-btn {
            transition: all 0.2s ease;
        }
        
        .file-close-btn:hover {
            transform: scale(1.1);
        }
    </style>
</head>
<body class="bg-[var(--bg-primary)] text-[var(--text-primary)] transition-colors duration-200">
<div class="flex h-screen">
    <!-- 侧边栏 -->
    <div id="sidebar" class="sidebar w-72 md:w-64 bg-[var(--bg-secondary)] border-r border-[var(--border-color)] flex flex-col z-30">
        <div class="p-4 border-b border-[var(--border-color)]">
            <button id="new-chat-btn" onclick="createNewConversation()"
                    class="w-full px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors">
                新建对话
            </button>
        </div>
        <div class="flex-1 overflow-y-auto" id="conversation-list">
            <!-- 对话列表将在这里动态生成 -->
        </div>
    </div>

    <!-- 主内容区 -->
    <div class="flex-1 flex flex-col">
        <!-- 顶部标题栏 -->
        <div class="p-4 md:p-4 p-1 border-b border-[var(--border-color)] flex justify-between items-center">
            <div class="flex-1 min-w-0 flex items-center space-x-2">
                <!-- 移动端菜单按钮 -->
                <button id="menu-toggle" class="md:hidden p-1 rounded-lg hover:bg-[var(--hover-bg)] z-20">
                    <svg class="w-5 h-5 text-gray-600 dark:text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
                    </svg>
                </button>
                <!-- 对话标题 -->
                <div class="flex-1 min-w-0 flex items-center">
                    <h2 id="current-conversation-title" 
                        class="text-lg md:text-lg font-medium cursor-pointer truncate max-w-[200px] md:max-w-[320px] lg:max-w-[500px] hover:text-[var(--button-primary-bg)]"
                        onclick="startEditingTitle(this)"></h2>
                    <input type="text" 
                            id="title-input"
                            class="hidden w-full max-w-[200px] md:max-w-[320px] lg:max-w-[500px] px-2 py-1 border border-[var(--border-color)] rounded bg-[var(--bg-primary)] text-[var(--text-primary)]"
                            onblur="saveTitle()"
                            onkeypress="handleTitleKeyPress(event)">
                </div>
            </div>
            <div class="flex items-center space-x-1 flex-shrink-0">
                <!-- 主题切换按钮 -->
                <button id="theme-toggle" class="p-1 md:p-2 rounded-lg hover:bg-[var(--hover-bg)] transition-colors">
                    <!-- 暗色模式图标 -->
                    <svg id="dark-icon" class="w-5 h-5 md:w-6 md:h-6 text-[var(--text-primary)]" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
                        <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path>
                    </svg>
                    <!-- 亮色模式图标 -->
                    <svg id="light-icon" class="w-5 h-5 md:w-6 md:h-6 text-[var(--text-primary)]" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
                        <path fill-rule="evenodd" d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" clip-rule="evenodd"></path>
                    </svg>
                </button>
                <!-- 设置按钮 -->
                <button id="system-prompt-btn" 
                        class="flex items-center space-x-1 px-1.5 py-0.5 md:px-3 md:py-1.5 rounded-md hover:bg-[var(--hover-bg)] transition-colors"
                        onclick="openSystemPromptModal()">
                    <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                              d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
                    </svg>
                </button>
            </div>
        </div>

        <!-- 聊天内容区 -->
        <div id="chat-container" class="flex-1 overflow-y-auto p-4 md:p-4 p-2 pb-safe">
            <div id="messages" class="max-w-3xl mx-auto space-y-4"></div>
        </div>

        <!-- 输入区域 -->
        <div class="input-area">
            <div class="max-w-3xl mx-auto flex flex-col space-y-4">
                <div class="relative">
                    <!-- 添加文件上传按钮 -->
                    <div class="absolute top-1 left-2">
                        <input type="file" id="file-upload" accept=".txt,.pdf,.docx,.doc,.xlsx,.xls" class="hidden" onchange="handleFileUpload(this)" multiple>
                        <button onclick="document.getElementById('file-upload').click()"
                                class="p-2.5 text-[var(--text-secondary)] hover:bg-[var(--hover-bg)] rounded-md transition-colors duration-200"
                                title="上传一个或多个文件">
                            <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                      d="M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" />
                            </svg>
                        </button>
                    </div>
                    <textarea id="user-input" rows="3"
                              class="resize-none w-full px-12 py-2 pr-36 border border-[var(--border-color)] rounded-md bg-[var(--bg-primary)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--button-primary-bg)]"
                              placeholder="输入消息... (Ctrl+Enter 发送)"></textarea>
                    <div class="absolute top-1 right-2">
                        <div class="flex items-center justify-between">
                            <select id="model-select" 
                                    onchange="switchModel(this.value)"
                                    class="pl-2 pr-2 p-2.5 text-sm rounded-md bg-[var(--bg-primary)] text-[var(--text-primary)] focus:ring-2 focus:ring-[var(--button-primary-bg)] cursor-pointer hover:bg-[var(--hover-bg)] transition-colors">
                            </select>
                        </div>
                    </div>
                    <div class="absolute bottom-2 right-2 flex items-center space-x-1.5">
                        <button onclick="clearCurrentChat()"
                                    class="p-2.5 text-[var(--text-secondary)] hover:bg-[var(--hover-bg)] rounded-md transition-colors duration-200"
                                    title="清空对话">
                                <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                        d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                                </svg>
                            </button>
                            <button onclick="togglePause()"
                                    class="hidden p-2.5 text-[var(--text-secondary)] hover:bg-[var(--hover-bg)] rounded-md transition-colors duration-200"
                                    id="pause-button">
                                <svg id="pause-icon" class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                        d="M10 9v6m4-6v6m7-3a9 9 0 11-18 0 9 9 0 0118 0z" />
                                </svg>
                                <svg id="play-icon" class="hidden w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                        d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                        d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                                </svg>
                            </button>
                            <button onclick="stopGeneration()"
                                    class="hidden p-2.5 text-[var(--text-secondary)] hover:bg-[var(--hover-bg)] rounded-md transition-colors duration-200"
                                    id="stop-button">
                                <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                        d="M6 18L18 6M6 6l12 12" />
                                </svg>
                            </button>
                            <button onclick="sendMessage()"
                                    class="p-2.5 text-[var(--button-primary-bg)] hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded-md transition-colors duration-200"
                                    id="send-button">
                                <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                        d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
                                </svg>
                        </button>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- 编辑消息的模态框 -->
<div id="edit-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center p-4 z-50">
    <div class="bg-[var(--bg-primary)] p-6 rounded-lg w-full max-w-2xl">
        <h3 class="text-lg font-semibold mb-4 text-[var(--text-primary)]">编辑消息</h3>
        <textarea id="edit-content" rows="6"
                  class="w-full px-4 py-2 border border-[var(--border-color)] rounded-md bg-[var(--bg-primary)] text-[var(--text-primary)] mb-4">
            </textarea>
        <div class="flex justify-end space-x-4">
            <button onclick="closeEditModal()"
                    class="px-4 py-2 bg-[var(--bg-secondary)] text-[var(--text-primary)] rounded-md hover:bg-[var(--hover-bg)]">
                取消
            </button>
            <button onclick="saveEdit()"
                    class="px-4 py-2 bg-[var(--button-primary-bg)] hover:bg-[var(--button-primary-hover)] text-[var(--button-primary-text)] rounded-md">
                保存
            </button>
        </div>
    </div>
</div>

<!-- 添加遮罩层 -->
<div id="sidebar-overlay" class="fixed inset-0 bg-black bg-opacity-50 z-20 hidden md:hidden" onclick="toggleSidebar()"></div>

<button id="scroll-to-bottom-btn" class="hidden" onclick="scrollToBottom(true)">
    <div class="flex items-center space-x-2">
        <span>查看新消息</span>
        <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 14l-7 7m0 0l-7-7m7 7V3" />
        </svg>
    </div>
</button>

<!-- 自定义对话框 -->
<div id="custom-dialog" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center">
    <div class="bg-[var(--bg-primary)] rounded-lg shadow-xl max-w-sm w-[calc(100%-2rem)] md:w-full mx-4 transform transition-all">
        <div class="p-4">
            <h3 id="dialog-title" class="text-lg font-medium text-[var(--text-primary)] mb-2"></h3>
            <p id="dialog-message" class="text-[var(--text-secondary)] leading-relaxed"></p>
        </div>
        <div class="px-4 py-3 bg-[var(--bg-secondary)] rounded-b-lg flex justify-end space-x-2 md:space-x-3">
            <button id="dialog-cancel" 
                    class="flex-1 md:flex-none px-4 py-2 text-[var(--text-secondary)] hover:bg-[var(--hover-bg)] rounded-md transition-colors">
                取消
            </button>
            <button id="dialog-confirm" 
                    class="flex-1 md:flex-none px-4 py-2 bg-[var(--button-primary-bg)] text-white rounded-md hover:bg-[var(--button-primary-hover)] transition-colors">
                确定
            </button>
        </div>
    </div>
</div>

<!-- 自定义提示框 -->
<div id="custom-alert" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center">
    <div class="bg-[var(--bg-primary)] rounded-lg shadow-xl max-w-sm w-[calc(100%-2rem)] md:w-full mx-4 transform transition-all">
        <div class="p-4">
            <p id="alert-message" class="text-[var(--text-primary)] leading-relaxed"></p>
        </div>
        <div class="px-4 py-3 bg-[var(--bg-secondary)] rounded-b-lg flex justify-end">
            <button id="alert-confirm" 
                    class="flex-1 md:flex-none min-w-[120px] px-4 py-2 bg-[var(--button-primary-bg)] text-white rounded-md hover:bg-[var(--button-primary-hover)] transition-colors">
                确定
            </button>
        </div>
    </div>
</div>

<!-- 系统提示词设置对话框 -->
<div id="system-prompt-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center">
    <div class="bg-[var(--bg-primary)] rounded-lg shadow-xl max-w-2xl w-[calc(100%-2rem)] mx-4 transform transition-all">
        <div class="p-4 border-b border-[var(--border-color)]">
            <h3 class="text-lg font-medium">设置</h3>
        </div>
        <div class="p-4">
            <div class="space-y-2">
                <label class="block text-sm font-medium mb-1">系统提示词</label>
                <textarea id="system-prompt" rows="6" 
                        class="w-full p-2 border rounded-md bg-[var(--bg-primary)] text-[var(--text-primary)] border-[var(--border-color)]"
                        placeholder="设置AI助手的行为和风格..."></textarea>
            </div>
        </div>
        <div class="p-4 bg-[var(--bg-secondary)] rounded-b-lg flex justify-end space-x-2">
            <button onclick="closeSystemPromptModal()" 
                    class="px-4 py-2 rounded-md hover:bg-[var(--hover-bg)] transition-colors">
                取消
            </button>
            <button onclick="saveSystemPrompt()"
                    class="px-4 py-2 bg-[var(--button-primary-bg)] text-white rounded-md hover:bg-[var(--button-primary-hover)] transition-colors">
                保存
            </button>
            <div class="flex-1"></div>
            <!-- 导入按钮 -->
            <button onclick="importChat()"
                    class="p-2 rounded-lg hover:bg-[var(--hover-bg)] transition-colors flex items-center gap-2"
                    title="导入对话">
                <svg class="w-6 h-6 text-[var(--text-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                        d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
                </svg>
            </button>
            <!-- 导出按钮 -->
            <button onclick="exportCurrentChat()"
                    class="p-2 rounded-lg hover:bg-[var(--hover-bg)] transition-colors flex items-center gap-2"
                    title="导出对话">
                <svg class="w-6 h-6 text-[var(--text-primary)]" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                        d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" />
                </svg>
            </button>
        </div>
    </div>
</div>

<!-- 添加隐藏的文件输入元素 -->
<input type="file" id="chat-import" accept=".json" style="display: none;" onchange="handleFileImport(this)">

<script>
    // 设置 PDF.js worker 路径
    pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
</script>
<script>
    // API配置
    const API_CONFIG = {
        defaultUrl: 'https://open.bigmodel.cn/api/paas/v4/chat/completions', //用来生成标题的 key
        defaultKey: '4343afe401f046afa592b4fa4f33cdab.zRzWA4Thv2FYZ2ba',  // 用来生成标题的 key
        defaultModel: 'glm-4v-plus', // 用来生成标题的模型
        defaultSystemPrompt: '你是一位专业、友善且富有同理心的AI助手。你会根据问题的复杂程度调整回答方式：对于复杂问题，你会条理清晰地展示思考过程并给出详细解释；对于简单问题，你会直接给出准确简洁的答案。你善于倾听用户的需求，用平易近人的语气进行交流，在必要时会主动询问以更好地理解用户意图。你的回答始终保持客观专业，并在适当时候提供有见地的建议。',
        models: {
            //deepseek蒸馏模型
            'deepseek-r1-distill-qwen-32b': {
                name: 'r1-fast',
                type: 'thinking',
                url: 'https://0f68edf33a3a4219a5ab9d9ae6b3034c-cn-hangzhou.alicloudapi.com/compatible-mode/v1/chat/completions ',
                key: 'none',
            },
            //免费的大模型
            "glm-4v-plus": {
                name: '智谱flash',
                type: 'normal',
                url: 'https://open.bigmodel.cn/api/paas/v4/chat/completions',
                key: '4343afe401f046afa592b4fa4f33cdab.zRzWA4Thv2FYZ2ba',  // 智谱的免费模型
            },
            //可以新增更多的模型
        },
        contextCount: 20,  // 设置上下文消息数量
        chatTypes: {
            normal: {
                name: '普通对话',
                systemPrompt: '你是一位专业、友善且富有同理心的AI助手。你会根据问题的复杂程度调整回答方式：对于复杂问题，你会条理清晰地展示思考过程并给出详细解释；对于简单问题，你会直接给出准确简洁的答案。你善于倾听用户的需求，用平易近人的语气进行交流，在必要时会主动询问以更好地理解用户意图。你的回答始终保持客观专业，并在适当时候提供有见地的建议。'
            },
            translator:{
                name: '翻译助手',
                systemPrompt: '你是一个好用的翻译助手。请将我的中文翻译成英文，将所有非中文的翻译成中文。我发给你所有的话都是需要翻译的内容，你只需要回答翻译结果。翻译结果请符合中文的语言习惯。'
            },
            it: {
                name: 'IT专家',
                systemPrompt: '我希望你充当 IT 专家。我会向您提供有关我的技术问题所需的所有信息，而您的职责是解决我的问题。你应该使用你的项目管理知识，敏捷开发知识来解决我的问题。在您的回答中使用适合所有级别的人的智能、简单和易于理解的语言将很有帮助。用要点逐步解释您的解决方案很有帮助。我希望您回复解决方案，而不是写任何解释。'
            },
            redbook: {
                name: '小红书文案生成',
                systemPrompt: '小红书的风格是：很吸引眼球的标题，每个段落都加 emoji, 最后加一些 tag。请用小红书风格'
            },
            midjourney: {
                name: 'MJ提示词大师',
                systemPrompt: `从现在开始，你是一名中英翻译，你会根据我输入的中文内容，翻译成对应英文。请注意，你翻译后的内容主要服务于一个绘画AI，它只能理解具象的描述而非抽象的概念，同时根据你对绘画AI的理解，比如它可能的训练模型、自然语言处理方式等方面，进行翻译优化。由于我的描述可能会很散乱，不连贯，你需要综合考虑这些问题，然后对翻译后的英文内容再次优化或重组，从而使绘画AI更能清楚我在说什么。请严格按照此条规则进行翻译，也只输出翻译后的英文内容。 例如，我输入：一只想家的小狗。
你不能输出：
/imagine prompt:
A homesick little dog.
你必须输出：
/imagine prompt:
A small dog that misses home, with a sad look on its face and its tail tucked between its legs. It might be standing in front of a closed door or a gate, gazing longingly into the distance, as if hoping to catch a glimpse of its beloved home.
如果你明白了，请回复"我准备好了"，当我输入中文内容后，请以"/imagine prompt:"作为开头，翻译我需要的英文内容。
                `
            },
            pal: {
                name: '仙剑奇侠传文字游戏',
                systemPrompt: `可以和我玩仙剑奇侠传的游戏吗，你利用markdown语法生成游戏地图，回合制，我扮演李逍遥，要求分为战斗模式和走格子模式，走格子时利用投骰子移动和触发相关事件，要求附带UI，UI内包含游戏所必须的信息，你要扮演其它NPC，游戏系统，旁白等`
            }
        },
        search: {
            url: 'https://api.bochaai.com/v1/web-search',
            enabled: false,  // 控制是否启用搜索功能
            token: 'xxxxxxxxx'  // bochaai的api key
        }
    };

    // Markdown 配置
    marked.setOptions({
        breaks: true,
        gfm: true,
        highlight: function(code, language) {
            if (language && hljs.getLanguage(language)) {
                try {
                    return hljs.highlight(code, { language }).value;
                } catch (err) {}
            }
            return code;
        },
        langPrefix: 'hljs language-'
    });

    function processMathJax(element) {
        //TODO
        return;
    }

    // 状态变量
    let currentEditingMessage = null;
    let currentConversationId = null;
    let conversations = JSON.parse(localStorage.getItem('conversations') || '{}');
    console.log(localStorage.getItem('conversations'))
    let isPaused = false;
    let currentRequestController = null;
    let isGenerating = false;
    let autoScroll = true;

    // 主题管理
    const themeToggle = document.getElementById('theme-toggle');
    const html = document.documentElement;
    const thinkingHtml = `
                                <div class="think-container">
                                    <div class="think-header" onclick="toggleThinking(this)">
                                        <svg class="think-header-icon w-4 h-4 text-[var(--text-secondary)]" viewBox="0 0 20 20" fill="currentColor" style="transform: rotate(0deg);">
                                            <path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
                                        </svg>
                                        <span class="text-[var(--text-secondary)]">🤔 思考过程</span>
                                    </div>
                                    <div class="think-content" style="display: block;">
                                        <div class="markdown-body text-[var(--text-primary)]"></div>
                                    </div>
                                </div>
                                <div class="response-content markdown-body text-[var(--text-primary)] mt-4"></div>`;

    function initializeTheme() {
        html.classList.remove('no-transition');
        
        const userPreference = localStorage.getItem('theme');
        const systemPreference = window.matchMedia('(prefers-color-scheme: dark)').matches;

        if (userPreference === 'dark' || (!userPreference && systemPreference)) {
            html.classList.add('dark');
            document.documentElement.setAttribute('data-theme', 'dark');
        } else {
            html.classList.remove('dark');
            document.documentElement.setAttribute('data-theme', 'light');
        }
        updateThemeIcons();
    }

    function toggleTheme() {
        html.classList.add('no-transition');

        const isDark = html.classList.contains('dark');
        if (isDark) {
            html.classList.remove('dark');
            document.documentElement.setAttribute('data-theme', 'light');
            localStorage.setItem('theme', 'light');
        } else {
            html.classList.add('dark');
            document.documentElement.setAttribute('data-theme', 'dark');
            localStorage.setItem('theme', 'dark');
        }

        void html.offsetHeight;
        
        html.classList.remove('no-transition');

        showThemeToast(!isDark);
        updateThemeIcons();
    }

    function showThemeToast(isDark) {
        const existingToast = document.querySelector('.theme-toast');
        if (existingToast) {
            existingToast.remove();
        }

        const toast = document.createElement('div');
        toast.className = 'theme-toast';
        toast.textContent = `已切换至${isDark ? '暗色' : '亮色'}主题`;
        document.body.appendChild(toast);

        setTimeout(() => {
            toast.style.opacity = '0';
            setTimeout(() => toast.remove(), 300);
        }, 2000);
    }

    function updateThemeIcons() {
        const darkIcon = document.getElementById('dark-icon');
        const lightIcon = document.getElementById('light-icon');
        const isDark = html.classList.contains('dark');
        
        darkIcon.style.display = isDark ? 'block' : 'none';
        lightIcon.style.display = isDark ? 'none' : 'block';
    }

    // 移动端菜单控制
    function toggleSidebar() {
        const sidebar = document.getElementById('sidebar');
        const overlay = document.getElementById('sidebar-overlay');
        sidebar.classList.toggle('active');
        overlay.classList.toggle('active');
    }

    // 初始化应用
    function initialize() {
        initializeTheme();

        // 初始化模型选择下拉框
        const modelSelect = document.getElementById('model-select');
        Object.entries(API_CONFIG.models).forEach(([modelId, modelInfo]) => {
            const option = document.createElement('option');
            option.value = modelId;
            option.id = `model-${modelId}`;
            option.textContent = modelInfo.name;
            modelSelect.appendChild(option);
        });

        // 如果没有对话，创建一个新对话
        if (Object.keys(conversations).length === 0) {
            const conversationId = 'conv_' + Date.now();
            conversations[conversationId] = {
                title: '普通对话 1',
                messages: [],
                systemPrompt: API_CONFIG.chatTypes.normal.systemPrompt,
                type: 'normal'
            };
            saveConversations();
            currentConversationId = conversationId;
        } else {
            // 优先使用上一次选中的对话
            const lastSelectedId = localStorage.getItem('lastSelectedConversation');
            if (lastSelectedId && conversations[lastSelectedId]) {
                currentConversationId = lastSelectedId;
            } else {
                // 如果没有上次选中的对话或该对话已被删除，使用最新的对话
                currentConversationId = Object.keys(conversations)[0];
            }
        }

        // 刷新对话列表和消息
        refreshConversationList();
        // 先刷新消息，然后等待渲染完成后滚动
        refreshMessages();
        scrollWhenReady();

        // 更新当前对话标题
        document.getElementById('current-conversation-title').textContent = 
            conversations[currentConversationId].title;

        // 设置事件监听器
        document.getElementById('menu-toggle').addEventListener('click', toggleSidebar);
        themeToggle.addEventListener('click', toggleTheme);

        // 监听系统主题变化
        window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
            if (!localStorage.getItem('theme')) {
                if (e.matches) {
                    html.classList.add('dark');
                    document.documentElement.setAttribute('data-theme', 'dark');
                } else {
                    html.classList.remove('dark');
                    document.documentElement.setAttribute('data-theme', 'light');
                }
                updateThemeIcons();
            }
        });

        // 监听输入框回车事件
        document.getElementById('user-input').addEventListener('keydown', function(e) {
            if (e.key === 'Enter' && e.ctrlKey) {
                e.preventDefault();
                sendMessage();
            }
        });

        // 修改滚动监听器
        const chatContainer = document.getElementById('chat-container');
        chatContainer.addEventListener('scroll', function() {
            const scrollButton = document.getElementById('scroll-to-bottom-btn');
            const isNearBottom = this.scrollHeight - this.scrollTop - this.clientHeight < 100;
            scrollButton.classList.toggle('visible', !isNearBottom);
            // 当用户向上滚动时，禁用自动滚动
            if (!isNearBottom) {
                autoScroll = false;
            }
            // 当用户滚动到底部时，重新启用自动滚动
            if (isNearBottom) {
                autoScroll = true;
            }
        });

        // 恢复上次选择的模型
        const savedModel = localStorage.getItem('preferred-model');
        if (savedModel && API_CONFIG.models[savedModel]) {
            modelSelect.value = savedModel;
        } else {
            modelSelect.value = API_CONFIG.defaultModel;
        }

        // 初始化时更新模型按钮可见性
        updateModelButtonsVisibility();
    }

    // 添加新的滚动函数
    function scrollWhenReady() {
        const isWechat = /MicroMessenger/i.test(navigator.userAgent);
        if (isWechat) return;

        // 使用 requestAnimationFrame 确保在下一帧渲染时执行
        requestAnimationFrame(() => {
            const messagesDiv = document.getElementById('messages');
            const chatContainer = document.getElementById('chat-container');
            
            if (messagesDiv.children.length > 0) {
                chatContainer.scrollTop = chatContainer.scrollHeight;
            } else {
                // 如果还没有渲染完成，使用 MutationObserver 继续监听
                const observer = new MutationObserver((mutations, obs) => {
                    if (messagesDiv.children.length > 0) {
                        chatContainer.scrollTop = chatContainer.scrollHeight;
                        obs.disconnect();
                    }
                });
                
                observer.observe(messagesDiv, {
                    childList: true,
                    subtree: true
                });
            }
        });
    }

    // 对话管理功能
    async function createNewConversation() {
        // 显示对话类型选择对话框
        const type = await showChatTypeDialog();
        if (!type) return; // 用户取消了选择

        const conversationId = 'conv_' + Date.now();
        // 根据对话类型设置标题
        const typeName = API_CONFIG.chatTypes[type].name;
        const count = Object.values(conversations).filter(conv => conv.type === type).length + 1;
        const title = `${typeName} ${count}`;

        conversations[conversationId] = {
            title: title,
            messages: [],
            systemPrompt: API_CONFIG.chatTypes[type].systemPrompt,
            type: type
        };
        saveConversations();
        switchConversation(conversationId);
        refreshConversationList();
        updateModelButtonsVisibility();

        // 在手机端自动收起侧边栏
        if (window.innerWidth < 768) {
            const sidebar = document.getElementById('sidebar');
            const overlay = document.getElementById('sidebar-overlay');
            sidebar.classList.remove('active');
            overlay?.classList.remove('active');
        }
    }

    function switchConversation(conversationId) {
        // 如果正在生成，不允许切换对话
        if (isGenerating) {
            return;
        }

        // 移除之前的选中状态
        const previousActive = document.querySelector('.conversation-item.active');
        if (previousActive) {
            previousActive.classList.remove('active');
        }
        
        currentConversationId = conversationId;
        // 保存当前选中的对话ID
        localStorage.setItem('lastSelectedConversation', conversationId);
        
        document.getElementById('current-conversation-title').textContent =
            conversations[conversationId].title;
        document.getElementById('title-input').classList.add('hidden');
        document.getElementById('current-conversation-title').classList.remove('hidden');
        refreshMessages();
        
        // 检查是否在微信浏览器中
        scrollWhenReady();
        
        // 添加新的选中状态
        const newActive = document.querySelector(`.conversation-item[data-id="${conversationId}"]`);
        if (newActive) {
            newActive.classList.add('active');
        }

        // 检查当前选中的模型是否与对话类型匹配
        const currentType = getConversationType(conversations[conversationId]?.messages);
        const activeModel = document.querySelector('.model-btn.active')?.onclick.toString().match(/'([^']+)'/)?.[1];
        
        if (currentType !== 'none' && (!activeModel || API_CONFIG.models[activeModel].type !== 
            (currentType === 'deepseek' ? 'thinking' : 'normal'))) {
            // 自动选择匹配类型的第一个模型
            const matchingModel = Object.entries(API_CONFIG.models).find(([_, info]) => 
                info.type === (currentType === 'deepseek' ? 'thinking' : 'normal'))?.[0];
            if (matchingModel) {
                switchModel(matchingModel);
            }
        }

        // 更新模型按钮的可见性
        updateModelButtonsVisibility();

        // 在手机端自动收起侧边栏
        if (window.innerWidth < 768) {  // 768px 是 md 断点
            const sidebar = document.getElementById('sidebar');
            const overlay = document.getElementById('sidebar-overlay');
            sidebar.classList.remove('active');
            overlay?.classList.remove('active');
        }
    }

    async function deleteConversation(conversationId, event) {
        event.stopPropagation();
        if (!(await showDialog('删除确认', '确定要删除这个对话吗？'))) return;

        if (currentConversationId === conversationId) {
            const remainingIds = Object.keys(conversations);
            const currentIndex = remainingIds.indexOf(conversationId);
            // 获取前一个对话的 ID，如果没有前一个则获取下一个
            const nextId = remainingIds[currentIndex - 1] || remainingIds[currentIndex + 1];
            
            delete conversations[conversationId];
            saveConversations();

            if (nextId) {
                switchConversation(nextId);
            } else {
                createNewConversation();
            }
        } else {
            delete conversations[conversationId];
            saveConversations();
        }

        refreshConversationList();
    }

    function refreshConversationList() {
        const listElement = document.getElementById('conversation-list');
        listElement.innerHTML = '';

        // 获取当前时间
        const now = new Date();
        
        // 分组对话
        const groups = {
            today: { label: '今天', items: [] },
            week: { label: '最近一周', items: [] },
            earlier: { label: '更早', items: [] }
        };
        
        // 将对话按时间戳分组
        Object.entries(conversations).forEach(([id, conv]) => {
            // 从 ID 中提取时间戳
            const timestamp = parseInt(id.split('_')[1]);
            const date = new Date(timestamp);
            const diffDays = Math.floor((now - date) / (1000 * 60 * 60 * 24));
            
            if (diffDays < 1) {
                groups.today.items.push({ id, conv });
            } else if (diffDays <= 7) {
                groups.week.items.push({ id, conv });
            } else {
                groups.earlier.items.push({ id, conv });
            }
        });
        
        // 在每个组内按时间戳倒序排序
        Object.values(groups).forEach(group => {
            group.items.sort((a, b) => {
                const timeA = parseInt(a.id.split('_')[1]);
                const timeB = parseInt(b.id.split('_')[1]);
                return timeB - timeA;
            });
        });
        
        // 渲染分组
        Object.values(groups).forEach(group => {
            if (group.items.length > 0) {
                // 添加分组标题
                const groupTitle = document.createElement('div');
                groupTitle.className = 'px-4 py-1.5 text-xs text-[var(--text-secondary)] opacity-75';
                groupTitle.textContent = group.label;
                listElement.appendChild(groupTitle);
                
                // 渲染组内对话
                group.items.forEach(({ id, conv }) => {
                    const item = document.createElement('div');
                    item.setAttribute('data-id', id);
                    item.className = `conversation-item p-4 flex justify-between items-center ${
                        (isGenerating && id === currentConversationId) ? 'cursor-pointer' : (isGenerating ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer')} ${
                        (currentConversationId === id) ? 'active' : ''
                    }`;

                    const titleDiv = document.createElement('div');
                    titleDiv.className = 'flex-1 truncate mr-2';
                    titleDiv.textContent = conv.title;
                    item.onclick = (e) => {
                        if (!e.target.closest('button') && !isGenerating) {
                            switchConversation(id);
                        }
                    };

                    const deleteButton = document.createElement('button');
                    deleteButton.className = 'p-1 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded';
                    deleteButton.innerHTML = `
                        <svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
                        </svg>
                    `;
                    deleteButton.title = '删除对话';
                    deleteButton.onclick = (e) => deleteConversation(id, e);

                    item.appendChild(titleDiv);
                    item.appendChild(deleteButton);
                    listElement.appendChild(item);
                });
            }
        });
    }

    function saveConversations() {
        localStorage.setItem('conversations', JSON.stringify(conversations));
    }

    function createMessageElement(role, index) {
        const messageDiv = document.createElement('div');
        messageDiv.className = `message-container rounded-lg ${
            role === 'user'
                ? 'bg-[var(--message-bg-user)] ml-0 md:ml-12 py-3 px-4' // 用户消息使用更紧凑的垂直内边距
                : 'bg-[var(--message-bg-assistant)] mr-0 md:mr-12 p-4'  // 助手消息保持原有内边距
        }`;
        messageDiv.dataset.index = index;

        const containerDiv = document.createElement('div');
        containerDiv.className = 'flex items-start space-x-4';

        const avatar = document.createElement('div');
        avatar.className = `w-8 h-8 rounded-full flex items-center justify-center ${
            role === 'user' ? 'bg-gray-500' : 'bg-blue-600'
        }`;
        
        if (role === 'user') {
            avatar.innerHTML = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class="w-5 h-5"><path d='M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2'/><circle cx='12' cy='7' r='4'/></svg>`;
        } else {
            avatar.innerHTML = `<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' class="w-5 h-5"><path d='M12 2C6.5 2 2 6.5 2 12s4.5 10 10 11c.9 0 1.8-.1 2.6-.4'/><path d='M17.6 14.2c-.8.8-1.3 2-1.1 3.2.2 1.2 1.1 2.2 2.3 2.4 1.2.2 2.4-.3 3.2-1.1.8-.8 1.3-2 1.1-3.2-.2-1.2-1.1-2.2-2.3-2.4-1.2-.2-2.4.3-3.2 1.1z'/><path d='M9.4 9.8c.8-.8 1.3-2 1.1-3.2-.2-1.2-1.1-2.2-2.3-2.4-1.2-.2-2.4.3-3.2 1.1-.8.8-1.3 2-1.1 3.2.2 1.2 1.1 2.2 2.3 2.4 1.2.2 2.4-.3 3.2-1.1z'/><path d='M14.5 8.5l-5 7'/></svg>`;
        }

        const contentContainer = document.createElement('div');
        contentContainer.className = 'flex-1 min-w-0';

        const actionsDiv = document.createElement('div');
        actionsDiv.className = 'message-actions flex space-x-2';

        // 添加复制按钮
        const copyButton = document.createElement('button');
        copyButton.className = 'p-1 text-[var(--text-secondary)] hover:bg-[var(--hover-bg)] rounded';
        copyButton.innerHTML = `
            <svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                      d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
            </svg>
        `;
        copyButton.title = '复制消息';
        copyButton.onclick = (e) => {
            e.stopPropagation();
            const content = conversations[currentConversationId].messages[index].content;
            navigator.clipboard.writeText(content).then(() => {
                // 显示复制成功的 toast
                const toast = document.createElement('div');
                toast.className = 'copy-toast';
                toast.innerHTML = `
                    <svg class="w-5 h-5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
                    </svg>
                    <span>复制成功</span>
                `;
                document.body.appendChild(toast);
                
                // 2秒后移除 toast
                setTimeout(() => {
                    toast.remove();
                }, 2000);
            });
        };
        actionsDiv.appendChild(copyButton);

        // 编辑按钮
        const editButton = document.createElement('button');
        editButton.className = 'p-1 text-[var(--text-secondary)] hover:bg-[var(--hover-bg)] rounded';
        editButton.innerHTML = `
            <svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                      d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
            </svg>
        `;
        editButton.title = '编辑消息';
        editButton.onclick = () => openEditModal(index);

        // 重新生成按钮（仅对最后一条助手消息显示）
        if (role === 'assistant' && index === conversations[currentConversationId].messages.length - 1) {
            const regenerateButton = document.createElement('button');
            regenerateButton.className = 'p-1 text-[var(--text-secondary)] hover:bg-[var(--hover-bg)] rounded';
            regenerateButton.innerHTML = `
                <svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                          d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
                </svg>
            `;
            regenerateButton.title = '重新生成';
            regenerateButton.onclick = () => regenerateMessage(index);
            actionsDiv.appendChild(regenerateButton);
        }

        const deleteButton = document.createElement('button');
        deleteButton.className = 'p-1 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded';
        deleteButton.innerHTML = `
            <svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                      d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" />
            </svg>
        `;
        deleteButton.title = '删除消息';
        deleteButton.onclick = () => deleteMessage(index);

        actionsDiv.appendChild(editButton);
        actionsDiv.appendChild(deleteButton);

        const textDiv = document.createElement('div');
        textDiv.className = 'markdown-body text-[var(--text-primary)]';

        contentContainer.appendChild(actionsDiv);
        contentContainer.appendChild(textDiv);

        containerDiv.appendChild(avatar);
        containerDiv.appendChild(contentContainer);
        messageDiv.appendChild(containerDiv);

        document.getElementById('messages').appendChild(messageDiv);
        return textDiv;
    }

    function refreshMessages() {
        const messagesDiv = document.getElementById('messages');
        messagesDiv.innerHTML = '';

        if (currentConversationId && conversations[currentConversationId]) {
            conversations[currentConversationId].messages.forEach((msg, index) => {
                const textDiv = createMessageElement(msg.role, index);
                if (msg.role === 'assistant' && msg.type === 'thinking') {
                    try {
                        const parsedContent = JSON.parse(msg.content);
                        const { thinking: thinkingContent, content: finalContent } = parsedContent;
                        if (thinkingContent) {
                            // 如果有思考过程，显示完整的思考+回答结构
                            const container = document.createElement('div');
                            container.style.marginLeft = "-2.2rem"
                            container.style.marginTop = "1rem"
                            container.innerHTML = thinkingHtml;
                            
                            textDiv.appendChild(container);
                            const reasoningDiv = container.querySelector('.think-content .markdown-body');
                            const contentDiv = container.querySelector('.response-content');
                            reasoningDiv.innerHTML = marked.parse(thinkingContent);
                            contentDiv.innerHTML = marked.parse(finalContent);
                            
                            // 处理数学公式
                            processMathJax(reasoningDiv);
                            processMathJax(contentDiv);
                        }
                    } catch (error) {
                        // 如果解析失败，作为普通消息显示
                        const container = document.createElement('div');
                        container.style.marginLeft = "-2.2rem"
                        container.style.marginTop = "1rem"
                        container.className = 'markdown-body text-[var(--text-primary)]';
                        container.innerHTML = marked.parse(msg.content);
                        textDiv.appendChild(container);
                        
                        // 处理数学公式
                        processMathJax(container);
                    }
                } else {
                    const container = document.createElement('div');
                    container.style.marginLeft = "-2.2rem"
                    container.style.marginTop = "1rem"
                    container.className = 'markdown-body text-[var(--text-primary)]';
                    container.innerHTML = marked.parse(msg.content || '');
                    textDiv.appendChild(container);
                    
                    // 处理数学公式
                    processMathJax(container);
                }

                textDiv.querySelectorAll('pre code').forEach((block) => {
                    hljs.highlightElement(block);
                    addCopyButton(block);
                });
            });
            // 确保所有代码块都正确高亮
            messagesDiv.querySelectorAll('pre code').forEach((block) => {
                hljs.highlightElement(block);
                addCopyButton(block);
            });
            scrollToBottom();
        }
    }

    function addCopyButton(block) {
        // 添加复制按钮到代码块
        const pre = block.parentElement;
        const copyButton = document.createElement('button');
        copyButton.className = 'code-copy-btn';
        copyButton.innerHTML = `
            <svg class="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                        d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
            </svg>
        `;
        copyButton.title = '复制代码';
        copyButton.onclick = (e) => {
            e.stopPropagation();
            navigator.clipboard.writeText(block.textContent).then(() => {
                // 显示复制成功的 toast
                const toast = document.createElement('div');
                toast.className = 'copy-toast';
                toast.innerHTML = `
                    <svg class="w-5 h-5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
                    </svg>
                    <span>代码已复制</span>
                `;
                document.body.appendChild(toast);
                
                // 2秒后移除 toast
                setTimeout(() => {
                    toast.remove();
                }, 2000);
                
                // 按钮视觉反馈
                copyButton.classList.add('copied');
                setTimeout(() => {
                    copyButton.classList.remove('copied');
                }, 1000);
            });
        };
        pre.appendChild(copyButton);
    }

    // 添加搜索函数
    async function performSearch(query) {
        try {
            const response = await fetch(API_CONFIG.search.url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${API_CONFIG.search.token}`
                },
                body: JSON.stringify({ 
                    query,
                    freshness: "oneWeek",
                    summary : true })
            });
            
            if (!response.ok) {
                throw new Error('Search request failed');
            }
            
            const data = await response.json();
            return data.data.webPages.value || [];
        } catch (error) {
            console.error('Search error:', error);
            return [];
        }
    }

    // 提取生成消息的公共方法
    async function generateAssistantMessage(messages, assistantDiv, previousMessages = null) {
        let finalContent = '';
        let isThinking = false;
        let thinkingContent = '';
        let firstTokenReceived = false;

        // 添加加载动画
        assistantDiv.style.marginLeft = "-2.2rem";
        assistantDiv.style.marginTop = "1rem";
        assistantDiv.innerHTML = `
            <div class="loading-dots">
                <div class="dot"></div>
                <div class="dot"></div>
                <div class="dot"></div>
            </div>`;

        try {
            const modelId = document.getElementById('model-select').value;
            const modelConfig = API_CONFIG.models[modelId];
            const response = await fetch(modelConfig.url, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${modelConfig.key || API_CONFIG.defaultKey}`,
                    'X-DashScope-SSE': 'enable'
                },
                signal: currentRequestController.signal,
                body: JSON.stringify({
                    model: modelId,
                    messages: messages,
                    stream: true
                })
            });

            if (!response.ok) {
                const errorText = await response.text();
                throw new Error(`请求失败: ${response.status} ${errorText}`);
            }

            const reader = response.body.getReader();
            const decoder = new TextDecoder();

            while (true) {
                const {done, value} = await reader.read();
                if (done) break;

                const chunk = decoder.decode(value);
                const lines = chunk.split('\n');

                if (isPaused) {
                    const waitForResume = async () => {
                        while (isPaused) {
                            if (!currentRequestController) return false;
                            await new Promise(resolve => setTimeout(resolve, 10));
                        }
                        return true;
                    };
                    
                    const shouldContinue = await waitForResume();
                    if (!shouldContinue) return;
                }

                let isDone = false;
                for (const line of lines) {
                    const trimmedLine = line.trim();
                    if (trimmedLine === 'data: [DONE]') {
                        isDone = true;
                        break;
                    } else if (trimmedLine.startsWith('data:')) {
                        try {
                            const data = JSON.parse(trimmedLine.slice(5));
                            if (data.choices && data.choices[0]) {
                                const delta = data.choices[0].delta;
                                const content = delta.content || delta.reasoning_content;

                                if (content) {
                                    // 移除加载动画
                                    if (!firstTokenReceived) {
                                        firstTokenReceived = true;
                                        assistantDiv.innerHTML = '';
                                    }

                                    if (delta.reasoning_content) {
                                        if (!isThinking) {
                                            isThinking = true;
                                            thinkingContent = '';
                                            assistantDiv.innerHTML = thinkingHtml;
                                        }
                                        thinkingContent += content;
                                        const reasoningDiv = assistantDiv.querySelector('.think-content .markdown-body');
                                        reasoningDiv.innerHTML = marked.parse(thinkingContent);
                                        
                                        // 确保在思考过程更新时也滚动到底部
                                        if (autoScroll) {
                                            const chatContainer = document.getElementById('chat-container');
                                            requestAnimationFrame(() => {
                                                chatContainer.scrollTop = chatContainer.scrollHeight;
                                            });
                                        }
                                    } else {
                                        if (!finalContent && !isThinking) {
                                            // 如果是第一条内容且没有思考过程，创建普通响应容器
                                            assistantDiv.style.marginLeft = "-2.2rem"
                                            assistantDiv.style.marginTop = "1rem"
                                            assistantDiv.innerHTML = `<div class="markdown-body text-[var(--text-primary)]"></div>`;
                                        }
                                        finalContent += content;

                                        // 检查是否正在构建链接
                                        const isInLink = /\[([^\]]+)?(\]\([^\)]*)?$/.test(finalContent);
                                        const contentDiv = isThinking ? 
                                            assistantDiv.querySelector('.response-content') : 
                                            assistantDiv.querySelector('.markdown-body');

                                        // 只有在不在链接中时才渲染
                                        if (!isInLink) {
                                            contentDiv.innerHTML = marked.parse(finalContent);
                                            // 重新应用代码高亮和复制按钮
                                            contentDiv.querySelectorAll('pre code').forEach((block) => {
                                                hljs.highlightElement(block);
                                                addCopyButton(block);
                                            });
                                        }

                                        if (autoScroll) {
                                        	scrollToBottom(true);
                                        }
                                    }
                                }
                            }
                        } catch (e) {
                            console.error('Error parsing SSE data:', e);
                        }
                    }
                }
                if (isDone) {
                    break;
                }
            }

            let fullContent = '';
            if (thinkingContent) {
                fullContent = JSON.stringify({
                    thinking: thinkingContent,
                    content: finalContent
                });
            } else {
                fullContent = finalContent;
            }

            return {
                role: 'assistant',
                type: thinkingContent ? 'thinking' : 'normal',
                content: fullContent
            };

        } catch (error) {
            if (error.name === 'AbortError') {
                console.log('请求被取消');
                return null;
            } else {
                // 显示错误提示
                const toast = document.createElement('div');
                toast.className = 'fixed bottom-4 right-4 bg-red-500 text-white px-4 py-2 rounded-lg shadow-lg z-50';
                toast.textContent = error.message || '请求失败，请稍后重试';
                document.body.appendChild(toast);
                
                setTimeout(() => {
                    toast.remove();
                }, 3000);
                
                // 恢复到发送消息前的状态
                if (previousMessages) {
                    conversations[currentConversationId].messages = previousMessages;
                    refreshMessages();
                }
                
                return null;
            }
        }
    }

    // 重新生成消息
    async function regenerateMessage(index) {
        if (isGenerating) return;
        
        // 检查是否是最后一条消息
        if (index !== conversations[currentConversationId].messages.length - 1) {
            showAlert('只能重新生成最后一条消息');
            return;
        }
        
        // 获取用户消息
        const userMessage = conversations[currentConversationId].messages[index - 1];
        if (!userMessage || userMessage.role !== 'user') {
            showAlert('无法重新生成此消息');
            return;
        }

        // 保存当前状态
        const previousMessages = [...conversations[currentConversationId].messages];
        
        // 删除当前的助手回复
        conversations[currentConversationId].messages.splice(index, 1);
        
        // 初始化生成状态
        if (currentRequestController) {
            currentRequestController.abort();
        }
        currentRequestController = new AbortController();
        toggleSendStopButton(true);
        isGenerating = true;
        refreshConversationList();
        
        // 刷新消息显示，删除原来的消息
        refreshMessages();
        
        // 创建新的助手消息元素
        const assistantDiv = createMessageElement('assistant', index);
        
        // 准备消息上下文
        const messages = getMessagesWithContext();
        
        // 生成新的回复
        const newMessage = await generateAssistantMessage(messages, assistantDiv, previousMessages);
        
        if (newMessage) {
            conversations[currentConversationId].messages.push(newMessage);
            saveConversations();
        }
        
        // 重置状态
        currentRequestController = null;
        toggleSendStopButton(false);
        isGenerating = false;
        refreshConversationList();
        refreshMessages(); 
    }

    // 修改 sendMessage 函数，使用新的 generateAssistantMessage 方法
    async function sendMessage(autoSend = false) {
        const input = document.getElementById('user-input');
        const message = input.value.trim();
        const pendingFiles = window.pendingFiles;
        
        // 如果既没有消息也没有待发送的文件，则返回
        if ((!message && (!pendingFiles || pendingFiles.length === 0)) || isGenerating) return;
        
        if (!autoSend) {
            input.value = '';
        }
        
        // 移除文件预览
        const filePreviews = document.querySelectorAll('.file-preview');
        filePreviews.forEach(preview => preview.remove());

        // 构建完整的用户消息
        let fullMessage = '';
        if (pendingFiles && pendingFiles.length > 0) {
            if (pendingFiles.length === 1) {
                fullMessage = `我上传了一个文件：${pendingFiles[0].fileName}\n\n\`\`\`\n${pendingFiles[0].content}\n\`\`\``;
            } else {
                fullMessage = `我上传了 ${pendingFiles.length} 个文件：\n\n`;
                pendingFiles.forEach((file, index) => {
                    fullMessage += `### 文件 ${index + 1}：${file.fileName}\n\n\`\`\`\n${file.content}\n\`\`\`\n\n`;
                });
            }
            
            if (message) {
                fullMessage += '\n\n' + message;
            }
            
            // 清除待发送的文件
            window.pendingFiles = [];
        } else {
            fullMessage = message;
        }
        
        // 创建用户消息元素
        const userDiv = createMessageElement('user', conversations[currentConversationId].messages.length);
        userDiv.style.marginLeft = "-2.2rem";
        userDiv.style.marginTop = "1rem";
        userDiv.innerHTML = marked.parse(fullMessage);
        

        let searchResults = '';
        if (API_CONFIG.search.enabled) {
            const loadingDiv = document.createElement('div');
            loadingDiv.className = 'search-loading';
            loadingDiv.innerHTML = `
                <span>正在搜索相关信息</span>
                <div class="dots">
                    <div class="dot"></div>
                    <div class="dot"></div>
                    <div class="dot"></div>
                </div>
            `;
            userDiv.appendChild(loadingDiv);
            scrollToBottom(true);
            
            try {
                // 使用默认小模型判断是否需要搜索
                const searchCheckRequest = await fetch(API_CONFIG.defaultUrl, {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': `Bearer ${API_CONFIG.defaultKey}`
                    },
                    body: JSON.stringify({
                        model: API_CONFIG.defaultModel,
                        messages: [
                            {
                                role: 'system',
                                content: '你是一个搜索判断器。请根据用户的消息判断是否需要联网搜索。如果需要搜索，请直接返回"true"，否则返回"false"。不要任何多余的话。'
                            },
                            {
                                role: 'user',
                                content: fullMessage
                            }
                        ]
                    })
                });
                
                const searchCheckResponse = await searchCheckRequest.json();
                const needsSearch = searchCheckResponse.choices[0].message.content === 'true';
                
                if (needsSearch) {
                    // 如果需要搜索，生成搜索请求
                    const searchRequest = await fetch(API_CONFIG.defaultUrl, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization': `Bearer ${API_CONFIG.defaultKey}`
                        },
                        body: JSON.stringify({
                            model: API_CONFIG.defaultModel,
                            messages: [
                                {
                                    role: 'system',
                                    content: '你是一个搜索请求生成器。请根据用户的消息生成一个适合搜索的简洁查询语句，直接返回查询语句，不要任何多余的话。'
                                },
                                {
                                    role: 'user',
                                    content: fullMessage
                                }
                            ]
                        })
                    });
                    
                    const searchQuery = await searchRequest.json();
                    const results = await performSearch(searchQuery.choices[0].message.content);
                    loadingDiv.remove();
                    if (results.length > 0) {
                        searchResults = formatSearchResults(results);
                    }
                } else {
                    loadingDiv.remove();
                }
            } catch (error) {
                loadingDiv.remove();
                console.error('Search error:', error);
            }
        }
        
        if (currentRequestController) {
            currentRequestController.abort();
        }
        currentRequestController = new AbortController();
        toggleSendStopButton(true);
        
        autoScroll = true;
        scrollToBottom(true);

        const previousMessages = [...conversations[currentConversationId].messages];

        conversations[currentConversationId].messages.push({
            role: 'user',
            content: fullMessage,
            searchResults: searchResults,
            metadata: pendingFiles && pendingFiles.length > 0 ? {
                type: 'files',
                files: pendingFiles.map(file => ({
                    fileName: file.fileName,
                    fileType: file.type,
                    fileSize: file.size
                }))
            } : undefined
        });

        const assistantDiv = createMessageElement('assistant', conversations[currentConversationId].messages.length);
        
        isGenerating = true;
        refreshConversationList();

        const newMessage = await generateAssistantMessage(getMessagesWithContext(), assistantDiv, previousMessages);
        
        if (newMessage) {
            conversations[currentConversationId].messages.push(newMessage);
            
            // 如果这是第一轮对话且标题还是默认的，则自动生成标题
            if (conversations[currentConversationId].messages.length === 2) {
                try {
                    const titleResponse = await fetch(API_CONFIG.defaultUrl, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization': `Bearer ${API_CONFIG.defaultKey}`
                        },
                        body: JSON.stringify({
                            model: API_CONFIG.defaultModel,
                            messages: [
                                {
                                    role: 'system',
                                    content: '你是一个对话标题生成器。请根据用户的消息和AI的回复生成一个简短的标题（不超过15个字），直接返回标题文本，不要任何多余的话。标题要简洁且能反映对话的主要内容。'
                                },
                                {
                                    role: 'user',
                                    content: `用户问题：${fullMessage}\nAI回复：${newMessage.content}`
                                }
                            ]
                        })
                    });

                    const titleData = await titleResponse.json();
                    if (titleData.choices && titleData.choices[0] && titleData.choices[0].message) {
                        const newTitle = titleData.choices[0].message.content.trim();
                        conversations[currentConversationId].title = newTitle;
                        document.getElementById('current-conversation-title').textContent = newTitle;
                        refreshConversationList();
                    }
                } catch (error) {
                    console.error('获取标题失败:', error);
                }
            }
            
            saveConversations(); 
        }
        
        currentRequestController = null;
        toggleSendStopButton(false);
        isGenerating = false;
        refreshConversationList();
        refreshMessages(); 
    }

    function getMessagesWithContext() {
        const allMessages = conversations[currentConversationId].messages.map(msg => ({
            role: msg.role,
            content: msg.content
        }));
        const currentIndex = allMessages.length - 1;
        
        // 获取当前对话的系统提示词
        let systemPrompt = conversations[currentConversationId].systemPrompt || API_CONFIG.defaultSystemPrompt;
        
        // 如果有搜索结果，将其添加到系统提示词中，并添加引用说明
        if (allMessages.length > 0 && conversations[currentConversationId].messages[currentIndex].searchResults) {
            systemPrompt += '\n\n以下是与用户问题相关的搜索结果，你可以参考这些信息来回答。在引用信息时，请使用markdown格式的链接，例如：根据[来源1](链接)显示...。这样可以让用户直接点击查看原始来源：\n' + 
                conversations[currentConversationId].messages[currentIndex].searchResults;
        }
        
        // 如果消息数量小于等于上下文限制，返回所有消息
        if (allMessages.length <= API_CONFIG.contextCount) {
            return [
                { role: 'system', content: systemPrompt },
                ...allMessages
            ];
        }
        
        // 获取最近的几条消息作为上下文
        const contextMessages = allMessages.slice(-API_CONFIG.contextCount - 1);
        
        return [
            {
                role: 'system',
                content: `${systemPrompt}\n\n这是一段对话的继续，之前已经进行了 ${currentIndex - API_CONFIG.contextCount} 轮对话。`
            },
            ...contextMessages
        ];
    }

    function openEditModal(index) {
        const modal = document.getElementById('edit-modal');
        const textarea = document.getElementById('edit-content');

        currentEditingMessage = index;
        textarea.value = conversations[currentConversationId].messages[index].content;
        modal.classList.remove('hidden');
    }

    function closeEditModal() {
        const modal = document.getElementById('edit-modal');
        modal.classList.add('hidden');
        currentEditingMessage = null;
    }

    function saveEdit() {
        if (currentEditingMessage === null) return;

        const textarea = document.getElementById('edit-content');
        const newContent = textarea.value.trim();

        conversations[currentConversationId].messages[currentEditingMessage].content = newContent;
        saveConversations();
        refreshMessages();

        closeEditModal();
    }

    async function deleteMessage(index) {
        if (!(await showDialog('删除确认', '确定要删除这条消息吗？'))) return;

        conversations[currentConversationId].messages.splice(index, 1);
        saveConversations();
        refreshMessages();
    }

    async function clearCurrentChat() {
        if (!(await showDialog('清空确认', '确定要清空当前对话吗？'))) return;

        conversations[currentConversationId].messages = [];
        saveConversations();
        refreshMessages();
    }

    function scrollToBottom(force = false) {
        const chatContainer = document.getElementById('chat-container');
        const lastMessage = chatContainer.querySelector('#messages > div:last-child');
        const scrollButton = document.getElementById('scroll-to-bottom-btn');

        if (lastMessage) {
            requestAnimationFrame(() => {
                chatContainer.scrollTop = chatContainer.scrollHeight;

                // 更新按钮可见性
                const isNearBottom = chatContainer.scrollHeight - chatContainer.scrollTop - chatContainer.clientHeight < 100;
                scrollButton.classList.toggle('visible', !isNearBottom);
                
                // 当滚动到底部时，重新启用自动滚动
                if (isNearBottom) {
                    autoScroll = true;
                }
            });
        }
    }

    function toggleSendStopButton(isGenerating) {
        const sendButton = document.getElementById('send-button');
        const stopButton = document.getElementById('stop-button');
        const pauseButton = document.getElementById('pause-button');
        const newChatButton = document.getElementById('new-chat-btn');  // 添加这行

        if (isGenerating) {
            sendButton.disabled = true;
            sendButton.classList.add('opacity-50', 'cursor-not-allowed');
            stopButton.classList.remove('hidden');
            pauseButton.classList.remove('hidden');
            const pauseIcon = document.getElementById('pause-icon');
            const playIcon = document.getElementById('play-icon');
            pauseIcon.classList.remove('hidden');
            playIcon.classList.add('hidden');
            pauseButton.classList.add('text-[var(--text-secondary)]');
            
            // 禁用新建对话按钮
            newChatButton.disabled = true;
            newChatButton.classList.add('opacity-50', 'cursor-not-allowed');
        } else {
            sendButton.disabled = false;
            sendButton.classList.remove('opacity-50', 'cursor-not-allowed');
            stopButton.classList.add('hidden');
            pauseButton.classList.add('hidden');
            isPaused = false;
            
            // 启用新建对话按钮
            newChatButton.disabled = false;
            newChatButton.classList.remove('opacity-50', 'cursor-not-allowed');
        }
    }

    function stopGeneration() {
        if (currentRequestController) {
            currentRequestController.abort();
            currentRequestController = null;
            isPaused = false;
            toggleSendStopButton(false);
            isGenerating = false;
            refreshConversationList();  // 停止生成时更新列表
        }
    }

    function startEditingTitle(titleElement) {
        const input = document.getElementById('title-input');
        input.value = titleElement.textContent;
        titleElement.classList.add('hidden');
        input.classList.remove('hidden');
        input.focus();
        input.select();
    }

    function saveTitle() {
        const titleElement = document.getElementById('current-conversation-title');
        const input = document.getElementById('title-input');
        const newTitle = input.value.trim();
        
        if (newTitle && currentConversationId) {
            conversations[currentConversationId].title = newTitle;
            titleElement.textContent = newTitle;
            saveConversations();
            refreshConversationList();
        }
        
        titleElement.classList.remove('hidden');
        input.classList.add('hidden');
    }

    function handleTitleKeyPress(event) {
        if (event.key === 'Enter') {
            event.preventDefault();
            saveTitle();
        }
    }

    function togglePause() {
        const pauseButton = document.getElementById('pause-button');
        const pauseIcon = document.getElementById('pause-icon');
        const playIcon = document.getElementById('play-icon');
        isPaused = !isPaused;
        if (isPaused) {
            pauseIcon.classList.add('hidden');
            playIcon.classList.remove('hidden');
        } else {
            pauseIcon.classList.remove('hidden');
            playIcon.classList.add('hidden');
        }
    }

    function switchModel(modelId) {
        const modelSelect = document.getElementById('model-select');
        
        // 检查当前对话类型
        const currentType = getConversationType(conversations[currentConversationId]?.messages);
        
        // 如果已有对话，检查模型兼容性
        if (currentType !== 'none') {
            const modelType = API_CONFIG.models[modelId].type;
            const currentModelType = currentType === 'deepseek' ? 'thinking' : 'normal';
            
            if (modelType !== currentModelType) {
                showAlert('不能在同一个对话中混用深度思考模型和普通模型');
                // 恢复之前的选择
                modelSelect.value = localStorage.getItem('preferred-model') || 'deepseek-r1';
                return;
            }
        }
        
        // 保存选择的模型
        localStorage.setItem('preferred-model', modelId);
        // 更新下拉框的值
        modelSelect.value = modelId;
    }

    async function showDialog(title, message) {
        return new Promise((resolve) => {
            const dialog = document.getElementById('custom-dialog');
            const titleEl = document.getElementById('dialog-title');
            const messageEl = document.getElementById('dialog-message');
            const confirmBtn = document.getElementById('dialog-confirm');
            const cancelBtn = document.getElementById('dialog-cancel');

            titleEl.textContent = title;
            messageEl.textContent = message;
            dialog.classList.remove('hidden');

            const handleConfirm = () => {
                dialog.classList.add('hidden');
                cleanup();
                resolve(true);
            };

            const handleCancel = () => {
                dialog.classList.add('hidden');
                cleanup();
                resolve(false);
            };

            const cleanup = () => {
                confirmBtn.removeEventListener('click', handleConfirm);
                cancelBtn.removeEventListener('click', handleCancel);
            };

            confirmBtn.addEventListener('click', handleConfirm);
            cancelBtn.addEventListener('click', handleCancel);
        });
    }

    function showAlert(message) {
        return new Promise((resolve) => {
            const alert = document.getElementById('custom-alert');
            const messageEl = document.getElementById('alert-message');
            const confirmBtn = document.getElementById('alert-confirm');

            messageEl.textContent = message;
            alert.classList.remove('hidden');

            const handleConfirm = () => {
                alert.classList.add('hidden');
                confirmBtn.removeEventListener('click', handleConfirm);
                resolve();
            };

            confirmBtn.addEventListener('click', handleConfirm);
        });
    }

    // 添加函数来判断对话类型
    function getConversationType(messages) {
        if (!messages || messages.length === 0) return 'none';
        
        for (const msg of messages) {
            if (msg.role === 'assistant') {
                if (msg.type === 'thinking') return 'deepseek';
                if (msg.type === 'normal') return 'normal';
            }
        }
        return 'none';
    }

    // 添加更新模型按钮可见性的函数
    function updateModelButtonsVisibility() {
        const currentType = getConversationType(conversations[currentConversationId]?.messages);
        const modelSelect = document.getElementById('model-select');
        
        // 获取所有选项
        const options = Array.from(modelSelect.options);
        
        if (currentType === 'none') {
            // 新对话，显示所有选项
            options.forEach(opt => {
                opt.style.display = '';
            });
        } else {
            // 根据类型显示对应选项
            const targetType = currentType === 'deepseek' ? 'thinking' : 'normal';
            
            options.forEach(opt => {
                const modelInfo = API_CONFIG.models[opt.value];
                opt.style.display = modelInfo.type === targetType ? '' : 'none';
            });

            // 如果当前选中的模型类型不匹配，切换到第一个可用的模型
            const currentModelInfo = API_CONFIG.models[modelSelect.value];
            if (currentModelInfo.type !== targetType) {
                const firstMatchingOption = options.find(opt => 
                    API_CONFIG.models[opt.value].type === targetType && opt.style.display !== 'none'
                );
                if (firstMatchingOption) {
                    modelSelect.value = firstMatchingOption.value;
                }
            }
        }
    }

    function toggleThinking(header) {
        const content = header.nextElementSibling;
        const icon = header.querySelector('.think-header-icon');
        const isCollapsed = content.classList.contains('collapsed');
        
        // 如果要展开
        if (isCollapsed) {
            content.style.display = 'block';
            // 使用 requestAnimationFrame 确保 display 更改已应用
            requestAnimationFrame(() => {
                content.classList.remove('collapsed');
                icon.style.transform = 'rotate(0deg)';
            });
        } else {
            // 如果要收起
            content.classList.add('collapsed');
            icon.style.transform = 'rotate(-90deg)';
            // 等待动画完成后隐藏元素
            content.addEventListener('transitionend', function handler() {
                if (!content.classList.contains('collapsed')) return;
                content.style.display = 'none';
                content.removeEventListener('transitionend', handler);
            });
        }
    }


    function openSystemPromptModal() {
        const modal = document.getElementById('system-prompt-modal');
        const systemPrompt = document.getElementById('system-prompt');
        const currentChat = conversations[currentConversationId];
        
        systemPrompt.value = currentChat?.systemPrompt || API_CONFIG.defaultSystemPrompt;
        modal.classList.remove('hidden');
    }
    
    function closeSystemPromptModal() {
        document.getElementById('system-prompt-modal').classList.add('hidden');
    }
    
    function saveSystemPrompt() {
        const systemPrompt = document.getElementById('system-prompt').value.trim();
        
        // 保存到当前对话
        if (currentConversationId && conversations[currentConversationId]) {
            conversations[currentConversationId].systemPrompt = systemPrompt;
            saveConversations();
        }
        
        closeSystemPromptModal();
        showAlert('保存成功');
    }

    // 添加对话类型选择对话框
    function showChatTypeDialog() {
        return new Promise((resolve) => {
            const dialog = document.createElement('div');
            dialog.className = 'fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center';
            dialog.innerHTML = `
                <div class="bg-[var(--bg-primary)] rounded-lg shadow-xl max-w-sm w-[calc(100%-2rem)] mx-4">
                    <div class="p-4 border-b border-[var(--border-color)]">
                        <h3 class="text-lg font-medium">选择对话类型</h3>
                    </div>
                    <div class="p-4 space-y-4">
                        ${Object.entries(API_CONFIG.chatTypes).map(([key, type]) => `
                            <button class="w-full p-4 text-left rounded-lg border border-[var(--border-color)] hover:bg-[var(--hover-bg)] transition-colors"
                                    onclick="selectChatType('${key}')">
                                <div class="font-medium">${type.name}</div>
                            </button>
                        `).join('')}
                    </div>
                </div>
            `;
            document.body.appendChild(dialog);
            
            // 添加点击背景关闭的功能
            dialog.addEventListener('click', (e) => {
                if (e.target === dialog) {
                    document.body.removeChild(dialog);
                    resolve(null);
                }
            });
            
            // 添加选择类型的函数到 window
            window.selectChatType = (type) => {
                document.body.removeChild(dialog);
                resolve(type);
            };
        });
    }

    // 格式化搜索结果
    function formatSearchResults(results) {
        if (!results.length) return '';
        
        // Sort results by dateLastCrawled in descending order
        results.sort((a, b) => new Date(b.dateLastCrawled) - new Date(a.dateLastCrawled));
        
        // 使用 markdown 格式的链接
        return results.map((result, index) => {
            const sourceNumber = index + 1;
            return `[来源${sourceNumber}] ${result.name}
链接：[${result.url}](${result.url})
摘要：${result.summary}
---`;
        }).join('\n\n');
    }

    // 添加搜索开关按钮到设置面板
    function addSearchToggleToSettings() {
        const settingsDiv = document.querySelector('#system-prompt-modal .p-4');
        const searchToggle = document.createElement('div');
        searchToggle.className = 'space-y-2 mt-4';
        searchToggle.innerHTML = `
            <label class="flex items-center space-x-2">
                <input type="checkbox" id="search-toggle" 
                       class="rounded border-[var(--border-color)]"
                       ${API_CONFIG.search.enabled ? 'checked' : ''}>
                <span class="text-sm font-medium">启用联网搜索（Beta）</span>
            </label>
        `;
        
        settingsDiv.appendChild(searchToggle);
        
        // 添加切换事件
        document.getElementById('search-toggle').addEventListener('change', (e) => {
            API_CONFIG.search.enabled = e.target.checked;
            // 可以选择将设置保存到localStorage
            localStorage.setItem('search_enabled', e.target.checked);
        });
    }

    // 在页面加载时初始化搜索设置
    document.addEventListener('DOMContentLoaded', () => {
        // 从localStorage加载搜索设置
        const searchEnabled = localStorage.getItem('search_enabled');
        if (searchEnabled !== null) {
            API_CONFIG.search.enabled = searchEnabled === 'true';
        }
        
        // 添加搜索开关到设置面板
        addSearchToggleToSettings();
    });

    // 导入对话功能
    function importChat() {
        document.getElementById('chat-import').click();
    }

    async function handleFileImport(input) {
        const file = input.files[0];
        if (!file) return;

        try {
            const text = await file.text();
            const chatData = JSON.parse(text);

            // 验证导入的数据格式
            if (!chatData.title || !Array.isArray(chatData.messages)) {
                throw new Error('无效的对话文件格式');
            }

            // 创建新的对话 ID
            const conversationId = 'conv_' + Date.now();
            
            // 构建新的对话对象
            conversations[conversationId] = {
                title: chatData.title,
                messages: chatData.messages,
                systemPrompt: chatData.systemPrompt || API_CONFIG.defaultSystemPrompt,
                type: chatData.type || 'normal'
            };

            // 保存并切换到新导入的对话
            saveConversations();
            switchConversation(conversationId);
            refreshConversationList();
            
            // 显示成功提示
            showAlert('对话导入成功');
            
            // 关闭设置面板
            closeSystemPromptModal();
        } catch (error) {
            showAlert('导入失败：' + (error.message || '文件格式错误'));
        }

        // 清除文件输入，允许重复导入相同文件
        input.value = '';
    }

    // 修改导出函数，增加更多元数据
    function exportCurrentChat() {
        if (!currentConversationId || !conversations[currentConversationId]) {
            showAlert('没有可导出的对话');
            return;
        }

        const currentChat = conversations[currentConversationId];
        const chatData = {
            title: currentChat.title,
            messages: currentChat.messages,
            systemPrompt: currentChat.systemPrompt,
            type: currentChat.type,
            exportDate: new Date().toISOString(),
            version: '1.0'
        };

        // 创建 Blob 对象
        const blob = new Blob([JSON.stringify(chatData, null, 2)], { type: 'application/json' });
        
        // 创建下载链接
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `${currentChat.title}_${new Date().toISOString().split('T')[0]}.json`;
        
        // 触发下载
        document.body.appendChild(a);
        a.click();
        
        // 清理
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
    }

    // 修改文件处理函数
    async function handleFileUpload(input) {
        const files = input.files;
        if (!files || files.length === 0) return;
        
        // 检查文件总大小（限制为50MB）
        let totalSize = 0;
        for (let i = 0; i < files.length; i++) {
            totalSize += files[i].size;
        }
        
        if (totalSize > 50 * 1024 * 1024) {
            showAlert('文件总大小不能超过50MB');
            input.value = '';
            return;
        }
        
        // 显示加载中提示
        const loadingToast = document.createElement('div');
        loadingToast.className = 'copy-toast';
        loadingToast.innerHTML = `
            <svg class="w-5 h-5 text-blue-500 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
                <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
            </svg>
            <span>正在处理文件...</span>
        `;
        document.body.appendChild(loadingToast);

        try {
            // 处理每个文件
            for (let i = 0; i < files.length; i++) {
                const file = files[i];
                
                // 检查单个文件大小（限制为20MB）
                if (file.size > 20 * 1024 * 1024) {
                    showAlert(`文件 ${file.name} 大小不能超过20MB`);
                    continue;
                }
                
                let content = '';
                let fileType = file.type;
                let fileIcon = '';
                let encoding = '';
                
                // 根据文件类型处理
                const fileName = file.name.toLowerCase();
                
                if (fileName.endsWith('.xlsx') || fileName.endsWith('.xls')) {
                    // 处理 Excel 文件
                    fileType = fileName.endsWith('.xlsx') ? 'XLSX' : 'XLS';
                    fileIcon = `
                        <svg class="w-8 h-8 text-green-600" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M10 8h4m-4 4h4m-4 4h4" />
                        </svg>
                    `;
                    
                    // 读取 Excel 文件
                    const arrayBuffer = await file.arrayBuffer();
                    const workbook = XLSX.read(arrayBuffer, { type: 'array' });
                    
                    // 提取所有工作表的内容
                    let extractedText = '';
                    
                    // 遍历所有工作表
                    for (const sheetName of workbook.SheetNames) {
                        const worksheet = workbook.Sheets[sheetName];
                        
                        // 将工作表转换为JSON
                        const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
                        
                        // 添加工作表名称
                        extractedText += `--- 工作表: ${sheetName} ---\n\n`;
                        
                        // 格式化数据为表格形式
                        if (jsonData.length > 0) {
                            // 获取最大列数
                            const maxCols = Math.max(...jsonData.map(row => row.length));
                            
                            // 生成表头行（A, B, C...）
                            let headerRow = '    ';
                            for (let i = 0; i < maxCols; i++) {
                                const colLetter = XLSX.utils.encode_col(i);
                                headerRow += colLetter.padEnd(15, ' ');
                            }
                            extractedText += headerRow + '\n';
                            
                            // 生成分隔行
                            extractedText += '    ' + '-'.repeat(maxCols * 15) + '\n';
                            
                            // 生成数据行
                            jsonData.forEach((row, rowIndex) => {
                                let rowText = `${(rowIndex + 1).toString().padStart(3, ' ')}|`;
                                
                                for (let i = 0; i < maxCols; i++) {
                                    const cellValue = row[i] !== undefined ? row[i].toString() : '';
                                    // 限制单元格内容长度，防止过长
                                    const truncatedValue = cellValue.length > 14 
                                        ? cellValue.substring(0, 11) + '...' 
                                        : cellValue;
                                    rowText += truncatedValue.padEnd(15, ' ');
                                }
                                
                                extractedText += rowText + '\n';
                            });
                        } else {
                            extractedText += '(空工作表)\n';
                        }
                        
                        extractedText += '\n\n';
                    }
                    
                    content = extractedText;
                } else if (fileName.endsWith('.docx')) {
                    // 处理 DOCX 文件
                    fileType = 'DOCX';
                    fileIcon = `
                        <svg class="w-8 h-8 text-blue-600" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M10 10.5h4m-4 3h4m-4 3h4" />
                        </svg>
                    `;
                    
                    // 读取 DOCX 文件
                    const arrayBuffer = await file.arrayBuffer();
                    const result = await mammoth.extractRawText({ arrayBuffer });
                    content = result.value || '';
                    
                    // 如果内容为空，尝试提取 HTML 并转换为纯文本
                    if (!content.trim()) {
                        const htmlResult = await mammoth.convertToHtml({ arrayBuffer });
                        const tempDiv = document.createElement('div');
                        tempDiv.innerHTML = htmlResult.value;
                        content = tempDiv.textContent || '';
                    }
                } else if (fileName.endsWith('.doc')) {
                    // 处理 DOC 文件
                    fileType = 'DOC';
                    fileIcon = `
                        <svg class="w-8 h-8 text-blue-600" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M10 10.5h4m-4 3h4m-4 3h4" />
                        </svg>
                    `;
                    
                    // 读取 DOC 文件
                    const arrayBuffer = await file.arrayBuffer();
                    const result = await mammoth.extractRawText({ arrayBuffer });
                    content = result.value || '';
                    
                    // 如果内容为空，尝试提取 HTML 并转换为纯文本
                    if (!content.trim()) {
                        const htmlResult = await mammoth.convertToHtml({ arrayBuffer });
                        const tempDiv = document.createElement('div');
                        tempDiv.innerHTML = htmlResult.value;
                        content = tempDiv.textContent || '';
                    }
                } else if (file.type === 'application/pdf' || fileName.endsWith('.pdf')) {
                    // 处理 PDF 文件
                    fileType = 'PDF';
                    fileIcon = `
                        <svg class="w-8 h-8 text-red-500" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M12 11v6m-3-3h6" />
                        </svg>
                    `;
                    
                    // 读取 PDF 文件
                    const arrayBuffer = await file.arrayBuffer();
                    const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;
                    
                    // 提取文本内容
                    const numPages = pdf.numPages;
                    let extractedText = '';
                    
                    for (let i = 1; i <= numPages; i++) {
                        const page = await pdf.getPage(i);
                        const textContent = await page.getTextContent();
                        const pageText = textContent.items.map(item => item.str).join(' ');
                        extractedText += `--- 第 ${i} 页 ---\n${pageText}\n\n`;
                    }
                    
                    content = extractedText;
                } else {
                    // 处理文本文件
                    fileType = 'TXT';
                    fileIcon = `
                        <svg class="w-8 h-8 text-[var(--text-secondary)]" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" 
                                  d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
                        </svg>
                    `;
                    
                    // 读取文件为 ArrayBuffer
                    const buffer = await file.arrayBuffer();
                    const uint8Array = new Uint8Array(buffer);
                    
                    // 尝试检测编码
                    const result = jschardet.detect(uint8Array);
                    encoding = result.encoding || 'GBK';  // 默认使用 GBK
                    
                    // 解码文件内容
                    try {
                        if (encoding.toUpperCase() === 'UTF-8') {
                            const decoder = new TextDecoder(encoding.toLowerCase());
                            content = decoder.decode(uint8Array);
                        } else {
                            // 对于非 UTF-8 编码，使用 TextDecoding polyfill
                            const gbkDecoder = new TextDecoder('gbk');
                            content = gbkDecoder.decode(uint8Array);
                        }

                        // 检查解码结果是否包含乱码（超过50%的字符是乱码）
                        const invalidChars = content.match(/\ufffd/g);
                        if (invalidChars && invalidChars.length > content.length * 0.5) {
                            throw new Error('检测到大量乱码字符');
                        }
                    } catch (e) {
                        console.warn('Failed to decode with detected encoding:', encoding);
                        // 强制使用 GBK 解码
                        const gbkDecoder = new TextDecoder('gbk');
                        content = gbkDecoder.decode(uint8Array);
                    }

                    // 检查是否有 BOM
                    if (content.charCodeAt(0) === 0xFEFF) {
                        content = content.slice(1);
                    }
                }

                // 如果内容为空，显示警告
                if (!content.trim()) {
                    showAlert(`文件 ${file.name} 内容为空或无法提取文本`);
                    continue;
                }
                
                // 创建文件预览元素
                const previewDiv = document.createElement('div');
                previewDiv.className = 'file-preview mb-2 p-3 bg-[var(--bg-secondary)] rounded-lg flex flex-col gap-2';
                previewDiv.innerHTML = `
                    <div class="flex items-center gap-3">
                        <div class="flex-shrink-0">
                            ${fileIcon}
                        </div>
                        <div class="flex-1 min-w-0">
                            <p class="text-sm font-medium text-[var(--text-primary)] truncate">${file.name}</p>
                            <p class="text-xs text-[var(--text-secondary)]">${fileType} ${(file.size / 1024).toFixed(1)}KB${encoding ? ' · ' + encoding : ''}</p>
                        </div>
                        <button class="file-close-btn p-1 text-[var(--text-secondary)] hover:text-[var(--button-primary-bg)] rounded-full hover:bg-[var(--hover-bg)] transition-colors" title="取消上传">
                            <svg class="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
                            </svg>
                        </button>
                    </div>
                `;

                // 为每个文件预览添加唯一ID
                const fileId = Date.now() + '-' + Math.random().toString(36).substr(2, 9);
                previewDiv.dataset.fileId = fileId;

                // 添加关闭按钮的点击事件
                const closeBtn = previewDiv.querySelector('.file-close-btn');
                closeBtn.addEventListener('click', function() {
                    // 移除文件预览
                    previewDiv.remove();
                    // 从待发送文件列表中移除
                    window.pendingFiles = window.pendingFiles.filter(f => f.id !== fileId);
                });

                // 将预览添加到消息区域
                const messagesDiv = document.getElementById('messages');
                messagesDiv.appendChild(previewDiv);

                // 存储文件内容到临时变量，等待发送
                // 确保 window.pendingFiles 已初始化
                if (!window.pendingFiles) {
                    window.pendingFiles = [];
                }
                
                window.pendingFiles.push({
                    id: fileId,
                    fileName: file.name || '未命名文件',
                    content: content || '',
                    size: file.size || 0,
                    type: fileType || '未知类型'
                });
            }

            // 自动滚动到底部
            scrollToBottom(true);
            
            // 移除加载提示
            loadingToast.remove();
            
            // 显示成功提示
            const toast = document.createElement('div');
            toast.className = 'copy-toast';
            toast.innerHTML = `
                <svg class="w-5 h-5 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
                </svg>
                <span>${files.length > 1 ? `${files.length} 个文件已上传` : '文件已上传'}</span>
            `;
            document.body.appendChild(toast);
            
            // 2秒后移除提示
            setTimeout(() => {
                toast.remove();
            }, 2000);
        } catch (error) {
            // 移除加载提示
            loadingToast.remove();
            
            showAlert('读取文件失败：' + (error.message || '文件格式不支持'));
        }

        // 清除文件输入，允许重复上传相同文件
        input.value = '';
    }

    initialize();
</script>
</body>
</html>
